Skip to content

fix(gui): pair the LAN switches, anchor the search row, and model pack order - #143

Merged
donislawdev merged 1 commit into
masterfrom
fix/gui-layout-and-fake-pack-order
Aug 20, 2026
Merged

fix(gui): pair the LAN switches, anchor the search row, and model pack order#143
donislawdev merged 1 commit into
masterfrom
fix/gui-layout-and-fake-pack-order

Conversation

@donislawdev

Copy link
Copy Markdown
Owner

Two layout complaints from using the program, and the harness fix that lets the suite check one of them.

The two LAN switches share a row

They are one decision seen from two sides. Stacked, each had half a card of empty space beside it
and the second read as an afterthought under the first rather than as its mirror.

A checkbox takes a whole row by kind - a long label clips in half a card - so columns=2 on the
section did nothing by itself. Field.span is tri-state now: None decides by kind, True claims a
row, False pairs the field with its neighbour. Only three BOOL fields exist in the whole registry
and narrow_filter keeps its own row, so the Settings window is untouched.

The render guard measured buttons only, which is how a clipped checkbox label could have shipped -
and this change puts the two longest ones side by side. It measures checkbuttons now. Verified at
1366x768 in both languages with the widget count printed, so the "OK" is not vacuous: four checkboxes
per language, none clipped, the Polish pair asking 249 px and 195 px and getting both.

The search row is anchored at both ends

Third shape, and the first two failed the same way. Everything packed LEFT was reported as "a stray
label floating above the first section with the whole width empty beside it"; everything packed RIGHT
drew the same report mirrored, and an alignment fix in between did not settle it either.

So the side was never the problem: a row with ONE cluster in it has a band of nothing beside that
cluster wherever the cluster goes. Both ends are anchored now - label and box at the left margin, note
and count at the right - which is the shape the Connections toolbar already uses and nobody has
complained about. Measured: the label lands on the section cards' own left edge, 12 px further left
than it sat before, and the count ends a pixel from their right edge. On the Connections page that
label is flush with its table, so the two pages now agree about where a search box lives.

The idle state is the one the page is looked at in, so the right end carries Ctrl+F while the box is
empty - otherwise the row drops straight back into the rejected shape whenever nobody is searching.
Same label, same fixed width, so nothing moves when it turns into a position counter.

The fake tkinter models pack order

It answered pack_slaves in CREATION order while its docstring claimed pack order. Measured: pack A,
then pack B with before=a, and it still answered [A, B].

That is not cosmetic. A widget re-packed above an existing sibling looked right in the suite and landed
under the whole page on real Tk - exactly what the Control page does when a preference brings its search
bar back, which is why that order could until now only be checked by rendering. The parent keeps an
ordered list; pack appends, honours before=/after= and MOVES an already-packed widget;
pack_forget removes it. The test that had to settle for "the call carried before=" now asserts the
bar is back above the page body.

Written against __dict__ rather than getattr(w, "x", None): __getattr__ answers any unknown
attribute with a no-op callable, so the default never arrives and the "not set yet" branch is
unreachable. That bit the first draft of this fix.

Verification

293 guards covering everything touched, ruff, mypy, the GUI smoke and the real-Tk render check in
both languages. Four new entries in the mutation registry, all caught - plus one repaired: an older
entry quoted span=True on lan_mode and the bookkeeping check caught it going stale, which is what
that check is for.

Two existing tests were asserting "cleared = blank" as a proxy for "no position is shown" and now say
which idle text they mean.

Looked at on the live window as well, since two of the three are about how the page reads.

…k order

Three things, and the third is what lets the suite check the first two.

The two LAN switches now share a row. They are one decision seen from two
sides, and stacked they left half a card of nothing beside each while the
second read as an afterthought under the first. A checkbox takes a whole row BY
KIND (a long label clips in half a card), so Field.span became tri-state:
None decides by kind, True claims a row, False pairs. Only three BOOL fields
exist and narrow_filter keeps its own row, so the Settings window is untouched.

The CI render guard measured buttons only, which is how a clipped CHECKBOX
label could have shipped - and this change puts the two longest ones side by
side. It measures checkbuttons now. Verified at 1366x768 in both languages with
the widget count printed, so the OK is not vacuous: four per language, none
clipped, the Polish pair asking 249 and 195 px and getting both.

The Control search bar is on its THIRD shape and the first two failed the same
way: everything packed left was "a stray label floating above the first section
with the whole width empty beside it", and everything packed right drew the same
report mirrored. The side was never the problem - a row with ONE cluster has a
band of nothing beside it wherever the cluster goes. Both ends are anchored now,
which is the shape the Connections toolbar already uses. Measured: the label
lands on the section cards' own left edge, 12 px further left than before, and
the count ends a pixel from their right. The idle state is the one the page is
looked at in, so the right end carries Ctrl+F while the box is empty, in the
same fixed-width label the count uses.

The fake tkinter answered pack_slaves in CREATION order while its docstring
claimed pack order. Measured: pack A, then pack B with before=a, and it still
said [A, B]. So a widget re-packed above an existing sibling looked right in the
suite and landed under the whole page on real Tk - exactly what the search bar
does when a preference brings it back, and why that order could until now only
be checked by rendering. The parent keeps an ordered list; pack honours
before=/after= and MOVES an already-packed widget. Written against __dict__,
because __getattr__ answers any unknown attribute with a no-op callable and the
"not set yet" branch is otherwise unreachable - that bit the first draft.

Guards: the harness ordering itself, the switches sharing a row, and the two
search tests that were asserting "cleared = blank" as a proxy for "no position".
Four MUTATIONS entries, all caught, plus one repaired: an older entry quoted
span=True on lan_mode and the bookkeeping check caught it going stale.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@donislawdev
donislawdev merged commit 3c331f5 into master Aug 20, 2026
13 of 14 checks passed
@donislawdev
donislawdev deleted the fix/gui-layout-and-fake-pack-order branch August 20, 2026 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant